package spring.cloud.tasks.executor.executor.waitingExecuteTasks;

import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

@Slf4j
public class SlidingTimeTaskBucketQueueService {
    private final SlidingTimeTaskBucketQueue slidingTimeTaskBucketQueue = new SlidingTimeTaskBucketQueue();
    /**
     * 每次并发调度的应用数量
     */
    private static final int MAX_APP_NUM = 8;

    private void scheduleTask(List<TaskInfo> taskInfoList) {
        long nowTime = System.currentTimeMillis();
        Lists.partition(taskInfoList, MAX_APP_NUM).parallelStream().forEach(taskItemList1 -> {
            try {
                //推入时间轮中等待调度执行
                taskItemList1.forEach(taskInfo -> {
                    long nextFireDate = taskInfo.getNextFireDate().getTime();
                    long delay = 0;
                    if (nextFireDate < nowTime) {
                        log.warn("超期未执行的任务:" + JSON.toJSONString(taskInfo));
                    } else {
                        delay = nextFireDate - nowTime;
                    }
                    scheduleTask(taskInfo, delay);
                });
            } catch (Exception e) {
                log.error("schedule failed." + e.getMessage(), e);
            }
        });
    }

    //如果立即执行，那么需要真正执行的时候必须大于理论上的触发时间
    private static final long LONG_DELAY_THRESHOLD_MS = 5 * 1000;

    public void scheduleTask(TaskInfo taskInfo, Long delayMS) {
        if (delayMS <= LONG_DELAY_THRESHOLD_MS) {
            realSchedule(taskInfo, delayMS);
            return;
        } else {
            List<TaskInfo> taskInfoList = new ArrayList<>();
            taskInfoList.addAll(taskInfoList);
            slidingTimeTaskBucketQueue.addTask(taskInfoList);
        }
    }

    private void realSchedule(final TaskInfo taskInfo, Long delayMS) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(taskInfo);
            }
        }).start();
    }

    /**
     * 任务取消的可能性比较低
     */
    private void cancelTask(List<TaskInfo> taskInfoList) {
        for (TaskInfo taskInfo : taskInfoList) {
            taskInfo.cancel();
        }
    }


    public void stop() {
        slidingTimeTaskBucketQueue.clear();
    }
}
